
package com.be.beadmin.design.impl;


import java.text.ParseException;
import java.text.SimpleDateFormat;
import cn.hutool.core.util.ObjectUtil;
import com.be.beadmin.basicData.entity.User;
import com.be.beadmin.basicData.repository.UserRepository;
import com.be.beadmin.common.entity.PageEntity;
import com.be.beadmin.common.exception.BeadminException;
import com.be.beadmin.common.utils.JpaQueryBuilder;
import com.be.beadmin.common.utils.JpaQueryBuilderNew;
import com.be.beadmin.common.utils.JpaSortBuilder;
import com.be.beadmin.design.dto.input.StandProductDto;
import com.be.beadmin.design.dto.output.StandProductEx;
import com.be.beadmin.design.entity.*;
import com.be.beadmin.design.mapper.StandProductMapper;
import com.be.beadmin.design.mapper.StandProductMapperEx;
import com.be.beadmin.design.repository.BopInfoRepository;
import com.be.beadmin.design.repository.StandFileInfoRepository;
import com.be.beadmin.design.repository.StandProductProcessInfoRepository;
import com.be.beadmin.design.repository.StandProductRepository;
import com.be.beadmin.design.service.BopInfoService;
import com.be.beadmin.design.service.StandFileInfoService;
import com.be.beadmin.design.service.StandProductService;
import com.be.beadmin.project.entity.BatchProduct;
import com.be.beadmin.project.repository.BatchProductRepository;
import com.be.beadmin.service.dto.output.DictDataEx;
import com.be.beadmin.service.entity.DictData;
import com.be.beadmin.service.entity.DictType;
import com.be.beadmin.service.entity.NotifyInfo;
import com.be.beadmin.service.repository.DictDataRepository;
import com.be.beadmin.service.repository.DictTypeRepository;
import com.be.beadmin.service.repository.NotifyInfoRepository;
import com.be.beadmin.service.repository.NotifyTemplateInfoRepository;
import com.be.beadmin.service.service.DictDataService;
import com.be.beadmin.service.service.NotifyInfoService;
import com.be.beadmin.service.service.NotifyTemplateInfoService;
import com.be.beadmin.service.service.SerialNumberService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Order;
import javax.persistence.criteria.Predicate;
import java.util.*;

/**
* @description 服务实现
* @author Jiahao Liu
* @date 2023-02-13
**/
@Service
@RequiredArgsConstructor
public class StandProductServiceImpl implements StandProductService {

    @Autowired
    private  StandProductRepository standProductRepository;
    @Autowired
    private  StandProductMapper standProductMapper;
    @Autowired
    private  StandProductMapperEx standProductExMapper;
    @Autowired
    private  StandProductService standProductService;
    @Autowired
    private DictTypeRepository dictTypeRepository;
    @Autowired
    private DictDataService dictDataService;

    @Autowired
    private DictDataRepository dictDataRepository;


    @Autowired
    private StandFileInfoService standFileInfoService;

    @Autowired
    private StandFileInfoRepository standFileInfoRepository;

    @Autowired
    private StandProductProcessInfoRepository standProductProcessInfoRepository;

    @Autowired
    private BopInfoRepository bopInfoRepository;

    @Autowired
    private BopInfoService bopInfoService;


    @Autowired
    private BatchProductRepository batchProductRepository;

    @Autowired
    private NotifyInfoRepository notifyInfoRepository;

    @Autowired
    private NotifyTemplateInfoService notifyTemplateInfoService;

    @Autowired
    private UserRepository userRepository;

    @Override
    public Page<StandProductEx> getStandProductByPage(PageEntity pageEntity) {
            Pageable pageable = PageRequest.of(
            pageEntity.getCurrent() -1,
            pageEntity.getPageSize());
            Page<StandProduct> page = standProductRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
                    List<Predicate> list = new ArrayList<>();
                    Predicate pre1 =   JpaQueryBuilderNew.getPredicate(root, pageEntity.getFilters(), criteriaBuilder);
                    list.add(pre1);
                    Predicate pre2 = criteriaBuilder.equal(root.get(StandProduct_.delete), 0); //过滤为0
                    list.add(pre2);
                    Predicate[] p = new Predicate[list.size()];
                    List<Order> orders = new ArrayList<>();
                    if(pageEntity.getSorters() != null && pageEntity.getSorters().size() > 0) {
                        orders = JpaSortBuilder.getPredicate(root, pageEntity.getSorters(), criteriaBuilder);
                        criteriaQuery.orderBy(orders);
                    } else {
                        criteriaQuery.orderBy(criteriaBuilder.desc(root.get(StandProduct_.createTime).as(Date.class)));
                    }
                    return  criteriaBuilder.and(list.toArray(p));
                    }
                    , pageable);
            Page<StandProductEx> page1 = page.map(standProductExMapper::toEntity);
            return page1;

    }

    @Override
    public StandProduct addStandProduct2(String standTypeDesc,String standTypeName, String bopCode, String standDesignWorkHour, String standManufactWorkHour, String memo,String bucket,String materialInfoId,    String materialCode,String materialName) throws Exception {

        StandProductDto standProductDto = new StandProductDto();

        DictType dictType = dictTypeRepository.findDictTypeByDictName("柜体类型");
        HashMap<String,String> list = dictDataService.getDictDataMapByDictTypeId(dictType);
        String prefix = list.get(standTypeDesc);

        DictType dictType1 = dictTypeRepository.findDictTypeByDictNameAndDelete("标准柜体各类型计数",0);
        if(dictType1==null) throw new BeadminException("未找到‘标准柜体各类型计数'字典");

        String postfix = "";
        int val = 0;
        List<DictData> dictDatas = dictDataRepository.findDictDataByDictTypeIdAndDelete(dictType1.getId(), 0);
        for (DictData dictData:dictDatas){
            String key = dictData.getKeyName();
            if(key.equals(standTypeDesc)){
                val = Integer.parseInt(dictData.getKeyValue());
                val += 1;
                postfix  = String.format("%03d", val);
                dictData.setKeyValue(String.valueOf(val));
                break;
            }
        }
        dictDataRepository.saveAll(dictDatas);

       // String postfix = serialNumberService.getNextSnByCode("StandTypeCodeSerial");

        String standTypeCode = "STD." + prefix + postfix + ".001"+".001" ; //STD.C(TYPE)XXX.001.001

        standProductDto.setStandTypeCode(standTypeCode);
        standProductDto.setStandTypeDesc(standTypeDesc);
        standProductDto.setStandTypeName(standTypeName);

        standProductDto.setBopCode(bopCode);

        standProductDto.setStandDesignWorkHour(Float.parseFloat(standDesignWorkHour));
        standProductDto.setStandManufactWorkHour(Float.parseFloat(standManufactWorkHour));

        standProductDto.setMaterialInfoId(materialInfoId);
        standProductDto.setMaterialCode(materialCode);
        standProductDto.setMaterialName(materialName);

        if(memo != null){
            if(memo.equals("null")) standProductDto.setMemo(null);
        }
        return standProductService.addStandProduct(standProductDto);
    }

    @Override
    public StandProduct addStandProduct(StandProductDto standProductDto) {
            StandProduct result = standProductRepository.findStandProductByIdAndDelete(standProductDto.getId(), 0);
            if(ObjectUtil.isNotEmpty(result)) {
                throw new BeadminException("StandProduct不存在,请重新查询");
            }
            StandProduct standProduct = standProductMapper.toEntity(standProductDto);
            standProduct.setIsBomUpload(0);
            standProduct.setIsDrawingUpload(0);
            standProduct.setBomSerial(0);
            standProduct.setDrawingSerial(0);
            standProduct.setState(0);
            standProductRepository.save(standProduct);


            List<BopInfo> bopInfoList = bopInfoRepository.findBopInfosByBopCode(standProduct.getBopCode());
            for(BopInfo bopInfo:bopInfoList){
                StandProductProcessInfo standProductProcessInfo=new StandProductProcessInfo();
                standProductProcessInfo.setStandTypeId(standProduct.getId());
                standProductProcessInfo.setStandTypeCode(standProduct.getStandTypeCode());
                standProductProcessInfo.setStandTypeName(standProduct.getStandTypeName());
                standProductProcessInfo.setStandTypeDesc(standProduct.getStandTypeDesc());

                standProductProcessInfo.setBopCode(bopInfo.getBopCode());
                standProductProcessInfo.setBopName(bopInfo.getBopName());

                standProductProcessInfo.setProcessId(bopInfo.getProcessId());
                standProductProcessInfo.setProcessCode(bopInfo.getProcessCode());
                standProductProcessInfo.setProcessName(bopInfo.getProcessName());
                standProductProcessInfo.setSequence(bopInfo.getSequence());

                standProductProcessInfo.setIsProductionProcess(bopInfo.getIsProductionProcess());

                standProductProcessInfo.setStandWorkHour(0);
                standProductProcessInfo.setStandCycle(0);
                standProductProcessInfoRepository.save(standProductProcessInfo);
            }
            return standProduct;
    }

    @Override
    public void updateStandProduct(StandProductDto standProductDto) {
            StandProduct standProduct = standProductRepository.findStandProductById(standProductDto.getId());
            standProduct = standProductMapper.toEntity(standProductDto);
            standProductRepository.save(standProduct);
    }

    @Override
    public void updateStandProduct2(String standTypeId,String standTypeDesc, String standTypeCode, String standTypeName, String bopCode, String standDesignWorkHour, String standManufactWorkHour,  String memo, String bucketName,String materialInfoId,String materialCode,String materialName) throws Exception {
        StandProduct standProduct = standProductRepository.findStandProductByIdAndDelete(standTypeId,0);
        //StandProduct standProduct = standProductRepository.findStandProductByStandTypeCodeAndDelete(standTypeCode,0);
        StandProductDto standProductDto = standProductMapper.toDto(standProduct);

        standProductDto.setStandTypeDesc(standTypeDesc);
        standProductDto.setStandTypeName(standTypeName);
        standProductDto.setBopCode(bopCode);

        standProductDto.setStandDesignWorkHour(Float.parseFloat(standDesignWorkHour));
        standProductDto.setStandManufactWorkHour(Float.parseFloat(standManufactWorkHour));

        standProductDto.setStandTypeCode(standTypeCode);
        standProductDto.setStandTypeDesc(standTypeDesc);
        standProductDto.setStandTypeName(standTypeName);

        standProductDto.setMaterialInfoId(materialInfoId);
        standProductDto.setMaterialCode(materialCode);
        standProductDto.setMaterialName(materialName);


        standProductDto.setMemo(memo);
        standProductService.updateStandProduct(standProductDto);
    }


    @Override
    public void delStandProduct(String id) {
        StandProduct standProduct = standProductRepository.findStandProductById(id);

        StringBuilder sb = new StringBuilder();

        /**
         * 0 未下发
         * 1 设计中
         * 2 工单下发
         * 3 生产中
         * 4
         * 。。。
         * -1 暂停
         */
        //找项目中的未下发的
        List<BatchProduct> batchProductList = batchProductRepository.findBatchProductByStandardProductCodeAndStateAndDelete(standProduct.getStandTypeCode(),0,0);

        if(batchProductList!=null&&batchProductList.size()>0){
            Set<String> codeSet = new HashSet<>();
            for(BatchProduct batchProduct:batchProductList){
                String projectCode = batchProduct.getProjectCode();
                if(!codeSet.contains(projectCode)){
                    sb.append("["+projectCode+"]");
                    codeSet.add(projectCode);
                }

            }

            if (!sb.toString().equals("")) {
                throw new BeadminException("项目编码为"+sb.toString()+"的项目柜体中,该标准柜存在未下发，无法删除" );
            }
        }else{
            //可以删除
            standProduct.setDelete(1);
            standProductRepository.save(standProduct);

            List<StandFileInfo> standFileInfoList = standFileInfoRepository.findStandFileInfoByStandTypeIdAndDelete(id,0);
            for (StandFileInfo standFileInfo : standFileInfoList) {
                standFileInfo.setDelete(1);
                standFileInfoRepository.save(standFileInfo);
            }

            List<StandProductProcessInfo> standProductProcessInfoList = standProductProcessInfoRepository.findStandProductProcessInfoByStandTypeIdAndDelete(id,0);
            for(StandProductProcessInfo standProductProcessInfo:standProductProcessInfoList){
                standProductProcessInfo.setDelete(1);
                standProductProcessInfoRepository.save(standProductProcessInfo);
            }
        }
    }

    @Override
    public void delStandProducts (List<String> ids) { }

    @Override
    public List<String> getProductType() {
        DictType dictType = dictTypeRepository.findDictTypeByDictName("柜体类型");
        List<DictDataEx> productType =  dictDataService.getDictDataExByDictTypeId(dictType);
        List<String> productTypeList = new ArrayList<>();
        productType.forEach(role-> productTypeList.add(role.getKeyName()));
        return productTypeList;
    }

    @Override
    public List<String> getDrawingTypeList() {
        DictType dictType = dictTypeRepository.findDictTypeByDictName("图纸类别");
        List<DictDataEx> drawingType =  dictDataService.getDictDataExByDictTypeId(dictType);
        List<String> drawingTypeList = new ArrayList<>();
        drawingType.forEach(role-> drawingTypeList.add(role.getKeyName()));
        return drawingTypeList;
    }

    // 图纸类别按字典值有序输出
    @Override
    public List<String> getDrawingTypeListSorted() {
        DictType dictType = dictTypeRepository.findDictTypeByDictName("图纸类别");
        List<DictDataEx> drawingType =  dictDataService.getDictDataExByDictTypeId(dictType);

        List<DictDataEx> res  = new ArrayList<>();
        for (DictDataEx item : drawingType){
            if (item.getKeyValue().equals("1")){
                res.add(item);
                drawingType.remove(item);
            }
        }
        res.addAll(drawingType);
        List<String> drawingTypeList = new ArrayList<>();
        res.forEach(role-> drawingTypeList.add(role.getKeyName()));
        return drawingTypeList;
    }

    @Override
    public StandProduct getStandProductByStandTypeName(String standTypeName) {
        StandProduct standProduct = standProductRepository.findStandProductByStandTypeNameAndDelete(standTypeName,0);
        return standProduct;
    }

    /**
     * 标准柜体，需要校验是否有BOM、图纸、工时，
     *
     * @param standProductCode
     * @return
     */
    @Override
    public void checkStandProduct(String standProductCode) {
        StringBuilder sb = new StringBuilder();
        StandProduct standProductByCode = getStandProductByCode(standProductCode);
        StandFileInfo bom = standFileInfoRepository.findStandFileInfoByStandTypeIdAndCategoryAndStatusAndDelete(standProductByCode.getId(), "BOM", 1, 0);
        if (bom == null) sb.append("没有启用中的Bom,");
        List<String> drawList = dictDataService.getDictDataKeyByDictTypeName("图纸类别");
        if (drawList == null) {
            throw new BeadminException("未找到图纸类别的字典");
        }
        List<StandFileInfo> standFileInfoDrawing = standFileInfoRepository.findStandFileInfoByStandTypeIdAndCategoryInAndStatusAndDelete(standProductByCode.getId(), drawList, 1, 0);
        if (standFileInfoDrawing.size() == 0) sb.append("没有图纸,");

        //检查工时是否不为0
        List<StandProductProcessInfo> standProductProcessInfoList = standProductProcessInfoRepository.findStandProductProcessInfoByStandTypeIdAndDelete(standProductByCode.getId(), 0);
        for(StandProductProcessInfo standProductProcessInfo:standProductProcessInfoList){
            float workHour = standProductProcessInfo.getStandWorkHour();
            if(workHour==0) sb.append(standProductProcessInfo.getProcessName()).append("没有标准工时");
        }


        if (!sb.toString().equals("")) {
            throw new BeadminException("该标准柜" + sb.toString());
        }
    }

    @Override
    public List<String>  submitStandProduct(String standTypeId) {
        List<String> result = new ArrayList<>();
        StandProduct standProduct = standProductRepository.findStandProductById(standTypeId);
        StandFileInfo bom = standFileInfoRepository.findStandFileInfoByStandTypeIdAndCategoryAndStatusAndDelete(standTypeId, "BOM", 1, 0);
        if (bom == null) result.add("没有启用的BOM。");
        List<StandFileInfo> standFileInfoDrawing = standFileInfoRepository.findStandFileInfosByStandTypeIdAndCategoryAndStatusAndDelete(standTypeId, "电气原理图", 1, 0);
        if (standFileInfoDrawing.size()==0) result.add("没有电气原理图。");
        standFileInfoDrawing = standFileInfoRepository.findStandFileInfosByStandTypeIdAndCategoryAndStatusAndDelete(standTypeId, "箱柜接线表", 1, 0);
        if (standFileInfoDrawing.size()==0) result.add("没有箱柜接线表。");

        //检查工时是否不为0
        List<StandProductProcessInfo> standProductProcessInfoList = standProductProcessInfoRepository.findStandProductProcessInfoByStandTypeIdAndDelete(standTypeId, 0);
        for(StandProductProcessInfo standProductProcessInfo:standProductProcessInfoList){
            float workHour = standProductProcessInfo.getStandWorkHour();
            if(workHour==0) {
                result.add("标准柜体工序标准工时不能为0。");
                break;
            }
        }
        if (result.size()==0){
            //能够提交送审
            standProduct.setState(1);//待审批
            standProductRepository.save(standProduct);

//            //-----------------------------------------------------------------------
//            // 异常填报人 发送 异常待处理 待办给  异常处理人
//            NotifyInfo notifyInfo =new NotifyInfo();
//            notifyInfo.setModuleName("技术管理");
//            notifyInfo.setFuncName("标准柜体审批");
//
//
//            notifyInfo.setNotifyDesc("标准柜体编码["+standProduct.getStandTypeCode()+"+]--标准柜体待审批");
//            notifyInfo.setNotifyType("待办");
//            User user = userRepository.findUserByIdAndDelete(standProduct.getUpdateId(),0);
//            if(user==null){
//                notifyInfo.setSenderName("-");
//            }else{
//                notifyInfo.setSenderId(user.getId());
//                notifyInfo.setSenderName(user.getName());
//            }
//            //设置日期格式
//            SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//            String formattedDate = formatter.format(new Date().getTime());
//
//            try {
//                notifyInfo.setSendTime(formatter.parse(formattedDate));
//            } catch (ParseException e) {
//                throw new RuntimeException(e);
//            }
//            notifyInfo = notifyInfoRepository.save(notifyInfo);
//
//            notifyTemplateInfoService.sendNotify(notifyInfo,-2,handlingMan,null);
        }

        return result;
    }

    @Override
    public void approveStandProduct(String standTypeId, Integer state, String approveText) {
        StandProduct standProduct =standProductRepository.findStandProductById(standTypeId);
        standProduct.setState(state);
        standProduct.setApproveText(approveText);
        standProductRepository.save(standProduct);
    }


    /**
     * 获取所有的柜体编码
     * @return
     */
    @Override
    public List<String> getStandProductCode() {
        List<String> standProductCodes = standProductRepository.findStandProductCodes();
        return standProductCodes;
    }

    /**
     * 获取标准柜体类型及编码信息
     *
     * @return
     */
    @Override
    public HashMap<String, List<String>> getStandProductAndType() {
        HashMap<String, List<String>> StandProductAndTypes = new HashMap<>();
        List<String> productTypes = getProductType();
        for (String productType:productTypes) {
            List<String> strings = new ArrayList<>();
            for (StandProduct standProduct : standProductRepository.findStandProductByStandTypeDescAndDelete(productType, 0)) {
                strings.add(standProduct.getStandTypeCode() + "——" +standProduct.getStandTypeName());
            }
            StandProductAndTypes.put(productType,strings);
        }
        return StandProductAndTypes;
    }

    /**
     * 获取标准柜体类型及编码信息
     *
     * @return
     */
    @Override
    public HashMap<String, List> getStandProductCodeAndName() {
        HashMap<String, List> StandProductAndTypes = new HashMap<>();
        List<String> productTypes = getProductType();
        for (String productType:productTypes) {
            List<Map<String,String>> strings = new ArrayList<>();
//            for (StandProduct standProduct : standProductRepository.findStandProductByStandTypeDescAndDelete(productType, 0)) {
//                Map<String,String> map = new HashMap<>();
//                map.put("standTypeCode",standProduct.getStandTypeCode());
//                map.put("productDesc",standProduct.getStandTypeName());
//                strings.add(map);
//            }
            for (StandProduct standProduct : standProductRepository.findStandProductByStandTypeDescAndStateAndDelete(productType,2, 0)) {
                Map<String,String> map = new HashMap<>();
                map.put("standTypeCode",standProduct.getStandTypeCode());
                map.put("productDesc",standProduct.getStandTypeName());
                map.put("materialCode",standProduct.getMaterialCode());
                map.put("materialName",standProduct.getMaterialName());
                strings.add(map);
            }
            StandProductAndTypes.put(productType,strings);
        }
        return StandProductAndTypes;
    }

    /**
     * 获取标准柜体类型及编码信息
     *
     * @return
     */
    @Override
    public StandProduct getStandProductByCode(String code) {
        return standProductRepository.findStandProductByStandTypeCodeAndDelete(code,0);
    }

    /**
     * 获取标准柜体类型及编码信息
     *
     * @return StandProductAndTypes
     */
    @Override
    public HashMap<String, String> getNoStandProductCode() {
        HashMap<String, String> StandProductAndTypes = new HashMap<>();
        DictType dictType = dictTypeRepository.findDictTypeByDictName("柜体类型");
        List<DictDataEx> productTypes =  dictDataService.getDictDataExByDictTypeId(dictType);
        for (DictDataEx productType:productTypes) {
            StandProductAndTypes.put(productType.getKeyName(),productType.getKeyValue());
        }
        return StandProductAndTypes;
    }


}